﻿namespace BathroomLocator.Services.Infrastructure
{
	using System;
	using System.Globalization;
	using System.ServiceModel.Activation;
	using System.Web;
	using System.Web.Routing;
	using Microsoft.WindowsAzure;
	using Microsoft.WindowsAzure.StorageClient;
	using WindowsPhone.Recipes.Push.Messasges;

	public static class Extensions
	{
		private const string ErrorResponse = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?><error {0}><code>{1}</code><message xml:lang=\"en-US\">{2}</message></error>";
		private const string DataServiceNamespace = "xmlns=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\"";

		public static Models.CloudBlob ToModel(this IListBlobItem blobItem, string userId, string accountName)
		{
			var blob = blobItem as Microsoft.WindowsAzure.StorageClient.CloudBlob;
			var sas = blob.GetSharedAccessSignature(new SharedAccessPolicy(), "readonly");
			var uriBuilder = new UriBuilder(blob.Uri) { Query = sas.TrimStart('?') };
			var blobUri = uriBuilder.Uri;
			var blobName = blobUri.LocalPath;

			// When using the Storage Emulator the first segment is the dev account, not the container.
			var devaccount = CloudStorageAccount.DevelopmentStorageAccount.Credentials.AccountName;
			if (accountName.Equals(devaccount, StringComparison.OrdinalIgnoreCase)
				&& blobName.StartsWith(string.Format(CultureInfo.InvariantCulture, "/{0}", devaccount), StringComparison.OrdinalIgnoreCase))
			{
				blobName = blobName.Remove(0, devaccount.Length + 1);
			}

			return new Models.CloudBlob
			{
				// Remove container name.
				BlobName = blobName.Remove(0, userId.Length + 1).TrimStart('/'),
				Uri = blobUri
			};
		}

		public static MessageSendResultLight SendAndHandleErrors(this PushNotificationMessage message, Uri uri)
		{
			var result = default(MessageSendResultLight);
			try
			{
				var sendResult = message.Send(uri);
				result = sendResult.NotificationStatus == NotificationStatus.Received
					? new MessageSendResultLight { Status = MessageSendResultLight.Success }
					: new MessageSendResultLight { Status = MessageSendResultLight.Error, Description = "The notification was not received by the device." };
			}
			catch (Exception exception)
			{
				result = new MessageSendResultLight { Status = MessageSendResultLight.Error, Description = exception.Message };
			}

			return result;
		}

		public static void EndWithDataServiceError(this HttpResponse response, int code, string error, string detail)
		{
			response.Clear();
			response.ContentType = HttpConstants.MimeApplicationAtomXml;
			response.StatusCode = code;
			response.StatusDescription = error;
			response.Write(string.Format(
				CultureInfo.InvariantCulture,
				ErrorResponse,
				DataServiceNamespace,
				error,
				detail));
			response.Flush();
			response.End();
			response.Clear();
		}

		public static void AddWcfServiceRoute(this RouteCollection routes, Type dataServiceType, string prefix)
		{
			routes.Add(new ServiceRoute(prefix, new AutomaticFormatServiceHostFactory(), dataServiceType));
		}

		public static void AddWcfServiceRoute<TService>(this RouteCollection routes, string prefix = "")
		{
			AddWcfServiceRoute(routes, typeof(TService), prefix);
		}
	}
}